Linux下CGroup进行CPU、内存等资源控制 | 您所在的位置:网站首页 › cpu 3855 › Linux下CGroup进行CPU、内存等资源控制 |
留存 from: http://www.cnblogs.com/kevingrace/p/5685433.html and http://www.cnblogs.com/wang_yb/p/3942208.html
CGroup 介绍 CGroup 是 Control Groups 的缩写,是 Linux 内核提供的一种可以限制、记录、隔离进程组 (process groups) 所使用的物力资源 (如 cpu memory i/o 等等) 的机制。2007 年进入 Linux 2.6.24 内核,CGroups 不是全新创造的,它将进程管理从 cpuset 中剥离出来,作者是 Google 的 Paul Menage。CGroups 也是 LXC 为实现虚拟化所使用的资源管理手段。 CGroup 功能及组成 CGroup 是将任意进程进行分组化管理的 Linux 内核功能。CGroup 本身是提供将进程进行分组化管理的功能和接口的基础结构,I/O 或内存的分配控制等具体的资源管理功能是通过这个功能来实现的。这些具体的资源管理功能称为 CGroup 子系统或控制器。CGroup 子系统有控制内存的 Memory 控制器、控制进程调度的 CPU 控制器等。运行中的内核可以使用的 Cgroup 子系统由/proc/cgroup 来确认。 CGroup 提供了一个 CGroup 虚拟文件系统,作为进行分组管理和各子系统设置的用户接口。要使用 CGroup,必须挂载 CGroup 文件系统。这时通过挂载选项指定使用哪个子系统。 Cgroups提供了以下功能: 1)限制进程组可以使用的资源数量(Resource limiting )。比如:memory子系统可以为进程组设定一个memory使用上限,一旦进程组使用的内存达到限额再申请内存,就会出发OOM(out of memory)。 2)进程组的优先级控制(Prioritization )。比如:可以使用cpu子系统为某个进程组分配特定cpu share。 3)记录进程组使用的资源数量(Accounting )。比如:可以使用cpuacct子系统记录某个进程组使用的cpu时间 4)进程组隔离(Isolation)。比如:使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间。 5)进程组控制(Control)。比如:使用freezer子系统可以将进程组挂起和恢复。 CGroup 支持的文件种类 表 1. CGroup 支持的文件种类 文件名 R/W 用途Release_agent RW 删除分组时执行的命令,这个文件只存在于根分组 Notify_on_release RW 设置是否执行 release_agent。为 1 时执行 Tasks RW 属于分组的线程 TID 列表 Cgroup.procs R 属于分组的进程 PID 列表。仅包括多线程进程的线程 leader 的 TID,这点与 tasks 不同 Cgroup.event_control RW 监视状态变化和分组删除事件的配置文件 CGroup 相关概念解释 1)任务(task)。在 cgroups 中,任务就是系统的一个进程; 2)控制族群(control group)。控制族群就是一组按照某种标准划分的进程。Cgroups 中的资源控制都是以控制族群为单位实现。一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个控制族群。一个进程组的进程可以使用 cgroups 以控制族群为单位分配的资源,同时受到 cgroups 以控制族群为单位设定的限制; 3)层级(hierarchy)。控制族群可以组织成 hierarchical 的形式,既一颗控制族群树。控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性; 4)子系统(subsystem)。一个子系统就是一个资源控制器,比如 cpu 子系统就是控制 cpu 时间分配的一个控制器。子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制。 相互关系 1)每次在系统中创建新层级时,该系统中的所有任务都是那个层级的默认 cgroup(我们称之为 root cgroup,此 cgroup 在创建层级时自动创建,后面在该层级中创建的 cgroup 都是此 cgroup 的后代)的初始成员; 2)一个子系统最多只能附加到一个层级; 3)一个层级可以附加多个子系统; 4)一个任务可以是多个 cgroup 的成员,但是这些 cgroup 必须在不同的层级; 5)系统中的进程(任务)创建子进程(任务)时,该子任务自动成为其父进程所在 cgroup 的成员。然后可根据需要将该子任务移动到不同的 cgroup 中,但开始时它总是继承其父任务的 cgroup。 图 1. CGroup 层级图
图 1 所示的 CGroup 层级关系显示,CPU 和 Memory 两个子系统有自己独立的层级系统,而又通过 Task Group 取得关联关系。 CGroup 特点 在 cgroups 中,任务就是系统的一个进程。 控制族群(control group)。控制族群就是一组按照某种标准划分的进程。Cgroups 中的资源控制都是以控制族群为单位实现。一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个控制族群。一个进程组的进程可以使用 cgroups 以控制族群为单位分配的资源,同时受到 cgroups 以控制族群为单位设定的限制。 层级(hierarchy)。控制族群可以组织成 hierarchical 的形式,既一颗控制族群树。控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性。 子系统(subsytem)。一个子系统就是一个资源控制器,比如 cpu 子系统就是控制 cpu 时间分配的一个控制器。子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制。 子系统的介绍 blkio -- 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等等)。 cpu -- 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问。 cpuacct -- 这个子系统自动生成 cgroup 中任务所使用的 CPU 报告。 cpuset -- 这个子系统为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点。 devices -- 这个子系统可允许或者拒绝 cgroup 中的任务访问设备。 freezer -- 这个子系统挂起或者恢复 cgroup 中的任务。 memory -- 这个子系统设定 cgroup 中任务使用的内存限制,并自动生成由那些任务使用的内存资源报告。 net_cls -- 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包。 图 2. CGroup 典型应用架构图
如图 2 所示,CGroup 技术可以被用来在操作系统底层限制物理资源,起到 Container 的作用。图中每一个 JVM 进程对应一个 Container Cgroup 层级,通过 CGroup 提供的各类子系统,可以对每一个 JVM 进程对应的线程级别进行物理限制,这些限制包括 CPU、内存等等许多种类的资源。下一部分会具体对应用程序进行 CPU 资源隔离进行演示。 cgroup的安装 其实安装很简单,最佳实践就是yum直接安装(centos下) 配置文件 1 2 3 4 5 6 7 8 9 10 [root@bastion-IDC ~]# vim /etc/cgconfig.conf mount { cpuset = /cgroup/cpuset; cpu =/cgroup/cpu; cpuacct =/cgroup/cpuacct; memory =/cgroup/memory; devices =/cgroup/devices; freezer =/cgroup/freezer; net_cls =/cgroup/net_cls; blkio =/cgroup/blkio; }cgroup section的语法格式如下: group { [] { = ; … } …} 其中: name: 指定cgroup的名称 permissions:可选项,指定cgroup对应的挂载点文件系统的权限,root用户拥有所有权限。 controller:子系统的名称 param name 和 param value:子系统的属性及其属性值 1.配置对mysql实例的资源限制1.1 修改cgconfig.conf文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 mount { cpuset =/cgroup/cpuset; cpu =/cgroup/cpu; cpuacct =/cgroup/cpuacct; memory =/cgroup/memory; blkio =/cgroup/blkio; } group mysql_g1 { cpu { cpu.cfs_quota_us = 50000; cpu.cfs_period_us = 100000; } cpuset { cpuset.cpus ="3"; cpusems ="0"; } cpuacct{ } memory { memory.limit_in_bytes=104857600; memory.swappiness=0; # memory.max_usage_in_bytes=104857600; # memory.oom_control=0; } blkio { blkio.throttle.read_bps_device="8:0 524288"; blkio.throttle.write_bps_device="8:0 524288"; } }1.2 配置文件的部分解释 cpu:cpu使用时间限额 cpu.cfs_period_us和cpu.cfs_quota_us来限制该组中的所有进程在单位时间里可以使用的cpu时间。这里的cfs是完全公平调度器的缩写。cpu.cfs_period_us就是时间周期(微秒),默认为100000,即百毫秒。cpu.cfs_quota_us就是在这期间内可使用的cpu时间(微秒),默认-1,即无限制。(cfs_quota_us是cfs_period_us的两倍即可限定在双核上完全使用)。cpuset:cpu绑定 我们限制该组只能在0一共1个超线程上运行。cpusems是用来设置内存节点的。 本例限制使用超线程0上的第四个cpu线程。 其实cgconfig也就是帮你把配置文件中的配置整理到/cgroup/cpuset这个目录里面,比如你需要动态设置mysql_group1/ cpuset.cpus的CPU超线程号,可以采用如下的办法。 [root@bastion-IDC ~]# echo "0" > mysql_group1/ cpuset.cpuscpuacct:cpu资源报告 memory:内存限制 内存限制我们主要限制了MySQL可以使用的内存最大大小memory.limit_in_bytes=256M。而设置swappiness为0是为了让操作系统不会将MySQL的内存匿名页交换出去。blkio:BLOCK IO限额 blkio.throttle.read_bps_device="8:0 524288"; #每秒读数据上限 blkio.throttle.write_bps_device="8:0 524288"; #每秒写数据上限 其中8:0对应主设备号和副设备号,可以通过ls -l /dev/sda查看 [root@bastion-IDC ~]# ls -l /dev/sda brw-rw----. 1 root disk 8, 0 Sep 15 04:19 /dev/sda 1.3 拓展知识 现在较新的服务器CPU都是numa结构,使用numactl --hardware可以看到numa各个节点的CPU超线程号,以及对应的节点号。 本例结果如下: [root@bastion-IDC ~]# numactl --hardware available: 1 nodes (0) node 0 cpus: 0 1 2 3 node 0 size: 1023 MB node 0 free: 68 MB node distances: node 0 0: 10 以下是较高端服务器的numa信息,仅作参考 [root@bastion-IDC ~]# numactl --hardware available: 4 nodes (0-3) node 0 cpus: 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 node 0 size: 16338 MB node 0 free: 391 MB node 1 cpus: 1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 node 1 size: 16384 MB node 1 free: 133 MB node 2 cpus: 2 6 10 14 18 22 26 30 34 38 42 46 50 54 58 62 node 2 size: 16384 MB node 2 free: 137 MB node 3 cpus: 3 7 11 15 19 23 27 31 35 39 43 47 51 55 59 63 node 3 size: 16384 MB node 3 free: 186 MB node distances: node 0 1 2 3 0: 10 20 30 20 1: 20 10 20 30 2: 30 20 10 20 3: 20 30 20 10 1.4 修改cgrules.conf文件 [root@bastion-IDC ~]# vim /etc/cgrules.conf # /etc/cgrules.conf #The format of this file is described in cgrules.conf(5) #manual page. # # Example: # #@student cpu,memory usergroup/student/ #peter cpu test1/ #% memory test2/ *:/usr/local/mysql/bin/mysqld * mysql_g1 注:共分为3个部分,分别为需要限制的实例,限制的内容(如cpu,memory),挂载目标。 2 使配置生效[root@bastion-IDC ~]# /etc/init.d/cgconfig restart Stopping cgconfig service: [ OK ] Starting cgconfig service: [ OK ] [root@localhost ~]# /etc/init.d/cgred restart Stopping CGroup Rules Engine Daemon... [ OK ] Starting CGroup Rules Engine Daemon: [ OK ] 注:重启顺序为cgconfig -> cgred ,更改配置文件后两个服务需要重启,且顺序不能错。 3 启动MySQL,查看MySQL是否处于cgroup的限制中[root@bastion-IDC ~]# ps -eo pid,cgroup,cmd | grep -i mysqld 29871 blkio:/;net_cls:/;freezer:/;devices:/;memory:/;cpuacct:/;cpu:/;cpuset:/ /bin/sh ./bin/mysqld_safe --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ 30219 blkio:/;net_cls:/;freezer:/;devices:/;memory:/;cpuacct:/;cpu:/;cpuset:/mysql_g1 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ --plugin-dir=/usr/local/mysql//lib/plugin --user=mysql --log-error=/usr/local/mysql/data//localhost.localdomain.err --pid-file=/usr/local/mysql/data//localhost.localdomain.pid --socket=/tmp/mysql.sock --port=3306 30311 blkio:/;net_cls:/;freezer:/;devices:/;memory:/;cpuacct:/;cpu:/;cpuset:/ grep -i mysqld 4 资源限制验证使用mysqlslap对mysql进行压力测试,看mysql使用资源是否超过限制 4.1 在shell窗口1用mysqlslap对mysql进行压力测试 [root@bastion-IDC ~]# /usr/local/mysql/bin/mysqlslap --defaults-file=/etc/my.cnf --concurrency=150 --iterations=1 --number-int-cols=8 --auto-generate-sql --auto-generate-sql-load-type=mixed --engine=innodb --number-of-queries=100000 -ujesse -pjesse --number-char-cols=35 --auto-generate-sql-add-autoincrement --debug-info -P3306 -h127.0.0.1
4.2 在shell窗口2查看mysql对cpu,内存的使用 可见:cpu限制在了第四个核心上,且对第四个核心的使用限制在50%。 4.3 在shell窗口3查看io的消耗
可见:mysql对io的读及写消耗均限制在2M每秒以内。 cgroup实例分析(手工动态验证)还原配置文件/etc/cgconfig.conf及/etc/cgrules.conf 为默认配置。测试实例依然为mysql,测试工具为mysqlslap。 开启cgconfig及cgrules 服务 [root@bastion-IDC ~]# /etc/init.d/cgconfig restart Stopping cgconfig service: [ OK ] Starting cgconfig service: [ OK ] [root@localhost /]# /etc/init.d/cgred restart Stopping CGroup Rules Engine Daemon... [ OK ] Starting CGroup Rules Engine Daemon: [ OK ] 开启mysqlslap压力测试程序 [root@localhost /]# /usr/local/mysql/bin/mysqlslap --defaults-file=/etc/my.cnf --concurrency=150 --iterations=1 --number-int-cols=8 --auto-generate-sql --auto-generate-sql-load-type=mixed --engine=innodb --number-of-queries=100000 -ujesse -pjesse --number-char-cols=35 --auto-generate-sql-add-autoincrement --debug-info -P3306 -h127.0.0.1 通过htop查看资源消耗。
限制mysql使用一个核,如第2个核,且对该核的使用不超过50% [root@bastion-IDC ~]# mkdir -p /cgroup/cpu/foo/ [root@bastion-IDC ~]# mkdir -p /cgroup/cpuset/foo/ [root@bastion-IDC ~]# echo 50000 > /cgroup/cpu/foo/cpu.cfs_quota_us [root@bastion-IDC ~]# echo 100000 > /cgroup/cpu/foo/cpu.cfs_period_us [root@bastion-IDC ~]# echo "0" > /cgroup/cpuset/foo/cpusems [root@bastion-IDC ~]# echo "1" > /cgroup/cpuset/foo/cpuset.cpus [root@bastion-IDC ~]# echo 28819 > /cgroup/cpu/foo/tasks 其中:28819为mysqld的进程号。
限制mysql使用内存为不超过512M 跑一个消耗内存脚本 1 2 3 4 #!/bin/bashx='a' while [ True ];do x=$x$x done;
内存的消耗在不断增加,对其进行限制,使其使用内存在500M以内 [root@bastion-IDC ~]# mkdir -p /cgroup/memory/foo [root@bastion-IDC ~]# echo 524288000 > /cgroup/memory/foo/memory.limit_in_bytes [root@bastion-IDC ~]# echo 44476 > /cgroup/memory/foo/tasks
跑一个消耗IO的测试 [root@bastion-IDC ~]# dd if=/dev/sda of=/dev/null 通过iotop看io占用情况,磁盘读取速度到了50M/s
[root@bastion-IDC ~]# mkdir -p /cgroup/blkio/foo [root@bastion-IDC ~]# echo '8:0 10485760' > /cgroup/blkio/foo/blkio.throttle.read_bps_device [root@bastion-IDC ~]# echo 45033 > /cgroup/blkio/foo/tasks 注1:45033为dd的进程号 注2:8:0对应主设备号和副设备号,可以通过ls -l /dev/sda查看 [root@bastion-IDC ~]# ls -l /dev/sda brw-rw----. 1 root disk 8, 0 Sep 15 04:19 /dev/sda cgroup小结使用cgroup临时对进程进行调整,直接通过命令即可,如果要持久化对进程进行控制,即重启后依然有效,需要写进配置文件/etc/cgconfig.conf及/etc/cgrules.conf ***************当你发现自己的才华撑不起野心时,就请安静下来学习吧***************
================================================================== ¥¥='$$' Linux资源控制-CPU和内存 http://www.cnblogs.com/wang_yb/p/3942208.html 主要介绍Linux下, 如果对进程的CPU和内存资源的使用情况进行控制的方法。 CPU资源控制 每个进程能够占用CPU多长时间, 什么时候能够占用CPU是和系统的调度密切相关的. Linux系统中有多种调度策略, 各种调度策略有其适用的场景, 也很难说哪种调度策略是最优的. Linux的调度策略可以参见代码: include/linux/sched.h /* * Scheduling policies */ #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 #define SCHED_BATCH 3 /* SCHED_ISO: reserved but not implemented yet */ #define SCHED_IDLE 5 /* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */ #define SCHED_RESET_ON_FORK 0x40000000 Linux 系统也提供了修改调度策略的命令和系统调用接口. 调用接口请查询相关文档, 这里主要介绍一下修改调度策略的命令 - chrt. # 在一个终端中执行 sleep 1000 # 打开另一个终端 ps -ef | grep sleep # 找出 sleep 1000 的pid, 这里假设是 1234 chrt -p 1234 # 可以查看 pid=1234 的进程的 调度策略, 输入如下: pid 1234's current scheduling policy: SCHED_OTHER pid 1234's current scheduling priority: 0 chrt -p -f 10 1234 # 修改调度策略为 SCHED_FIFO, 并且优先级为10 chrt -p 1234 # 再次查看调度策略 pid 1234's current scheduling policy: SCHED_FIFO pid 1234's current scheduling priority: 10 补充: chrt 也可以直接指定一条命令, 并设置这条命令的优先级的调度策略, 具体查看 chrt --help 查看一个进程的调度策略, 除了使用 chrt 命令之外, 还可以 cat /proc//sched 实时进程的CPU控制 所谓的实时进程, 也就是那些对响应时间要求比较高的进程. 这类进程需要在限定的时间内处理用户的请求, 因此, 在限定的这段时间内, 需要占用所有CPU资源, 并且不能被其它进程打断. 在这种情况下, 如果实时进程中出现了类似死循环之类的情况, 就会导致整个系统无响应. 因为实时进程的CPU优先级高, 并且未处理完之前是不会释放CPU资源的. 所以, 内核中需要有一种方式来限制实时进程的CPU资源占用. 系统整体设置 1. 获取当前系统的设置 sysctl -n kernel.sched_rt_period_us # 实时进程调度的单位CPU时间 1 秒 1000000 sysctl -n kernel.sched_rt_runtime_us # 实时进程在 1 秒中实际占用的CPU时间, 0.95秒 950000 这个设置说明实时进程在运行时并不是完全占用CPU的, 每1秒中有0.05秒的时间可以给其它进程运行. 这样既不会对实时进程的响应时间造成太大的影响, 也避免了实时进程卡住时导致整个系统无响应. 2. 设置实时进程占用CPU时间 上面的默认设置中, 实时进程占用 95% 的CPU时间. 如果觉得占用的太多或太少, 都是可以调整的.比如: sysctl -w kernel.sched_rt_runtime_us=900000 # 设置实时进程每1秒中只占0.9秒的CPU时间 kernel.sched_rt_runtime_us = 900000 sysctl -n kernel.sched_rt_runtime_us 900000 cgroup 中的设置 整体设置是针对整个系统的, 我们也可以通过 cgroup 来对一组进程的CPU资源进行控制. 如果想在 cgroup 中对 sched_rt_period_us 和 sched_rt_runtime_us 进行控制, 需要内核编译选项 CONFIG_RT_GROUP_SCHED=y 查看当前系统的内核编译选项方法如下: (debian 7.6 系统) cat /boot/config-`uname -r` 查看 CONFIG_RT_GROUP_SCHED 是否启用 cat /boot/config-`uname -r` | grep -i rt_group # CONFIG_RT_GROUP_SCHED is not set debian 7.6 默认没有启动这个选项, 所以挂载cgroup之后, 没有设置 sched_rt_period_us 和 sched_rt_runtime_us 的文件 mkdir /mnt/cgroup mount -t cgroup cgroup /mnt/cgroup/ cd /mnt/cgroup/ ls -l total 0 -r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_merged -r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_queued -r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_service_bytes -r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_serviced -r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_service_time -r--r--r-- 1 root root 0 Aug 28 09:06 blkio.io_wait_time --w------- 1 root root 0 Aug 28 09:06 blkio.reset_stats -r--r--r-- 1 root root 0 Aug 28 09:06 blkio.sectors -r--r--r-- 1 root root 0 Aug 28 09:06 blkio.time -rw-r--r-- 1 root root 0 Aug 28 09:06 blkio.weight -rw-r--r-- 1 root root 0 Aug 28 09:06 blkio.weight_device -rw-r--r-- 1 root root 0 Aug 28 09:06 cgroup.clone_children --w--w--w- 1 root root 0 Aug 28 09:06 cgroup.event_control -rw-r--r-- 1 root root 0 Aug 28 09:06 cgroup.procs -r--r--r-- 1 root root 0 Aug 28 09:06 cpuacct.stat -rw-r--r-- 1 root root 0 Aug 28 09:06 cpuacct.usage -r--r--r-- 1 root root 0 Aug 28 09:06 cpuacct.usage_percpu -rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.cpu_exclusive -rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.cpus -rw-r--r-- 1 root root 0 Aug 28 09:06 cpusem_exclusive -rw-r--r-- 1 root root 0 Aug 28 09:06 cpusem_hardwall -rw-r--r-- 1 root root 0 Aug 28 09:06 cpusemory_migrate -r--r--r-- 1 root root 0 Aug 28 09:06 cpusemory_pressure -rw-r--r-- 1 root root 0 Aug 28 09:06 cpusemory_pressure_enabled -rw-r--r-- 1 root root 0 Aug 28 09:06 cpusemory_spread_page -rw-r--r-- 1 root root 0 Aug 28 09:06 cpusemory_spread_slab -rw-r--r-- 1 root root 0 Aug 28 09:06 cpusems -rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.sched_load_balance -rw-r--r-- 1 root root 0 Aug 28 09:06 cpuset.sched_relax_domain_level -rw-r--r-- 1 root root 0 Aug 28 09:06 cpu.shares --w------- 1 root root 0 Aug 28 09:06 devices.allow --w------- 1 root root 0 Aug 28 09:06 devices.deny -r--r--r-- 1 root root 0 Aug 28 09:06 devices.list -rw-r--r-- 1 root root 0 Aug 28 09:06 net_cls.classid -rw-r--r-- 1 root root 0 Aug 28 09:06 notify_on_release -rw-r--r-- 1 root root 0 Aug 28 09:06 release_agent -rw-r--r-- 1 root root 0 Aug 28 09:06 tasks 果然, 只有cpu.share, 没有 cpu.sched_rt_period_us 和 cpu.sched_rt_runtime_us 没办法, 重新编译内核, 编译内核的具体方法参见: 编译Linux内核 为了节约时间, 我们用 make localmodconfig 来创建 .config 文件, 然后修改其中的 CONFIG_RT_GROUP_SCHED=y 下载源码等等参见: 编译Linux内核, 主要步骤如下: cd /path/to/linux-source-3.2 make localmodconfig vim .config # 设置 CONFIG_RT_GROUP_SCHED=y 并保存 make make modules_install make install reboot # 重启之前看看 /boot/grub/grub.cfg 中, 默认启动的是不是新安装的内核 启动到新内核, 再次查看内核选项 CONFIG_RT_GROUP_SCHED 是否启用 cat /boot/config-`uname -r` | grep -i rt_group CONFIG_RT_GROUP_SCHED=y # 已启用 再次挂载 cgroup 文件系统, 发现多了2个配置文件, cpu.rt_period_us 和 cpu.rt_runtime_us mount -t cgroup cgroup /mnt/cgroup/ cd /mnt/cgroup/ ls -l total 0 -r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_merged -r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_queued -r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_service_bytes -r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_serviced -r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_service_time -r--r--r-- 1 root root 0 Aug 28 09:53 blkio.io_wait_time --w------- 1 root root 0 Aug 28 09:53 blkio.reset_stats -r--r--r-- 1 root root 0 Aug 28 09:53 blkio.sectors -r--r--r-- 1 root root 0 Aug 28 09:53 blkio.time -rw-r--r-- 1 root root 0 Aug 28 09:53 blkio.weight -rw-r--r-- 1 root root 0 Aug 28 09:53 blkio.weight_device -rw-r--r-- 1 root root 0 Aug 28 09:53 cgroup.clone_children --w--w--w- 1 root root 0 Aug 28 09:53 cgroup.event_control -rw-r--r-- 1 root root 0 Aug 28 09:53 cgroup.procs -r--r--r-- 1 root root 0 Aug 28 09:53 cpuacct.stat -rw-r--r-- 1 root root 0 Aug 28 09:53 cpuacct.usage -r--r--r-- 1 root root 0 Aug 28 09:53 cpuacct.usage_percpu -rw-r--r-- 1 root root 0 Aug 28 09:53 cpu.rt_period_us -rw-r--r-- 1 root root 0 Aug 28 09:53 cpu.rt_runtime_us -rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.cpu_exclusive -rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.cpus -rw-r--r-- 1 root root 0 Aug 28 09:53 cpusem_exclusive -rw-r--r-- 1 root root 0 Aug 28 09:53 cpusem_hardwall -rw-r--r-- 1 root root 0 Aug 28 09:53 cpusemory_migrate -r--r--r-- 1 root root 0 Aug 28 09:53 cpusemory_pressure -rw-r--r-- 1 root root 0 Aug 28 09:53 cpusemory_pressure_enabled -rw-r--r-- 1 root root 0 Aug 28 09:53 cpusemory_spread_page -rw-r--r-- 1 root root 0 Aug 28 09:53 cpusemory_spread_slab -rw-r--r-- 1 root root 0 Aug 28 09:53 cpusems -rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.sched_load_balance -rw-r--r-- 1 root root 0 Aug 28 09:53 cpuset.sched_relax_domain_level -rw-r--r-- 1 root root 0 Aug 28 09:53 cpu.shares --w------- 1 root root 0 Aug 28 09:53 devices.allow --w------- 1 root root 0 Aug 28 09:53 devices.deny -r--r--r-- 1 root root 0 Aug 28 09:53 devices.list -rw-r--r-- 1 root root 0 Aug 28 09:53 net_cls.classid -rw-r--r-- 1 root root 0 Aug 28 09:53 notify_on_release -rw-r--r-- 1 root root 0 Aug 28 09:53 release_agent -rw-r--r-- 1 root root 0 Aug 28 09:53 tasks cat cpu.rt_period_us 1000000 cat cpu.rt_runtime_us 950000 通过配置 cpu.rt_period_us 和 cpu.rt_runtime_us 就可以对 cgroup 中的进程组中的实时进程进行 CPU使用时间的控制. 资源控制实例 上面主要介绍资源的一些理论基础, 下面通过一些实例演示如果通过 cgroup 来控制进程所使用的 CPU和内存 资源. Linux对CPU 和 内存的控制有对应的 cgroup 子系统 cpuset 和 memory 实例: cgroup 中对其中 *子cgroup* 的CPU资源控制 对各个 *子cgroup* 的CPU占用率进行控制主要依靠每个 *子cgroup* 的 cpu.shares 文件 直接用实验过程来说话, 其中加入了一些注释. # 安装需要的软件 apt-get install stress # 让CPU达到 100% 的压力工具 apt-get install sysstat # 查看系统CPU, 内存, 磁盘, 网络等资源使用情况的工具 实例1 - 默认情况, A 和 B 各占CPU总资源的 1/2 挂载 cgroup 文件系统 (注意加上 -o cpu 的选项) 在 cgroup中创建 2个子cgroup A 和 B 默认情况下, cgroup A 和 cgroup B 中的 cpu.shares 中的数值都是 1024 在 A 和 B 中用 stress 工具使其 CPU占用率达到 100% top 命令查看 A 和 B 中进程分别占用的 CPU (应该都是 50%) # 挂载 cgroup 文件系统 mount -t cgroup -o cpu cgroup /mnt/cgroup/ cd /mnt/cgroup ls -l total 0 -r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_merged -r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_queued -r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_service_bytes -r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_serviced -r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_service_time -r--r--r-- 1 root root 0 Aug 28 11:29 blkio.io_wait_time --w------- 1 root root 0 Aug 28 11:29 blkio.reset_stats -r--r--r-- 1 root root 0 Aug 28 11:29 blkio.sectors -r--r--r-- 1 root root 0 Aug 28 11:29 blkio.time -rw-r--r-- 1 root root 0 Aug 28 11:29 blkio.weight -rw-r--r-- 1 root root 0 Aug 28 11:29 blkio.weight_device -rw-r--r-- 1 root root 0 Aug 28 11:29 cgroup.clone_children --w--w--w- 1 root root 0 Aug 28 11:29 cgroup.event_control -rw-r--r-- 1 root root 0 Aug 28 11:29 cgroup.procs -r--r--r-- 1 root root 0 Aug 28 11:29 cpuacct.stat -rw-r--r-- 1 root root 0 Aug 28 11:29 cpuacct.usage -r--r--r-- 1 root root 0 Aug 28 11:29 cpuacct.usage_percpu -rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.cpu_exclusive -rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.cpus -rw-r--r-- 1 root root 0 Aug 28 11:29 cpusem_exclusive -rw-r--r-- 1 root root 0 Aug 28 11:29 cpusem_hardwall -rw-r--r-- 1 root root 0 Aug 28 11:29 cpusemory_migrate -r--r--r-- 1 root root 0 Aug 28 11:29 cpusemory_pressure -rw-r--r-- 1 root root 0 Aug 28 11:29 cpusemory_pressure_enabled -rw-r--r-- 1 root root 0 Aug 28 11:29 cpusemory_spread_page -rw-r--r-- 1 root root 0 Aug 28 11:29 cpusemory_spread_slab -rw-r--r-- 1 root root 0 Aug 28 11:29 cpusems -rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.sched_load_balance -rw-r--r-- 1 root root 0 Aug 28 11:29 cpuset.sched_relax_domain_level -rw-r--r-- 1 root root 0 Aug 28 11:29 cpu.shares --w------- 1 root root 0 Aug 28 11:29 devices.allow --w------- 1 root root 0 Aug 28 11:29 devices.deny -r--r--r-- 1 root root 0 Aug 28 11:29 devices.list -rw-r--r-- 1 root root 0 Aug 28 11:29 net_cls.classid -rw-r--r-- 1 root root 0 Aug 28 11:29 notify_on_release -rw-r--r-- 1 root root 0 Aug 28 11:29 release_agent -rw-r--r-- 1 root root 0 Aug 28 11:29 tasks # 创建 子cgroup A 和 B mkdir {A,B} cat A/cpu.shares 1024 cat B/cpu.shares 1024 # 在 A 和 B 中分别通过 stress 工具使其CPU使用率达到 100% echo ¥¥ > A/tasks # 将当前的 SHELL 加入到 cgroup A中 stress -c 2 # 这里-c 2 是因为测试机器是双核, 要在2个核上都产生 100% 的CPU 占用率 # 另外打开一个 shell 窗口, 并将这个shell 加入到 cgroup B中 echo ¥¥ > B/tasks # 将当前的 SHELL 加入到 cgroup B中 stress -c 2 # 在2个核上都产生 100% 的CPU 占用率 # 再打开一个 shell 窗口, 用top命令查看 CPU占用情况 top top - 14:10:32 up 43 min, 3 users, load average: 2.31, 1.24, 0.62 Tasks: 78 total, 5 running, 73 sleeping, 0 stopped, 0 zombie %Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 1887872 total, 114744 used, 1773128 free, 10472 buffers KiB Swap: 3982332 total, 0 used, 3982332 free, 45068 cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3350 root 20 0 6524 92 0 R 49.9 0.0 0:08.73 stress 3351 root 20 0 6524 92 0 R 49.9 0.0 0:08.67 stress 3353 root 20 0 6524 92 0 R 49.9 0.0 0:07.35 stress 3354 root 20 0 6524 92 0 R 49.9 0.0 0:07.36 stress # 查看这 4 个stress 进程是否分别属于 A 和 B cat /mnt/cgroup/A/tasks 2945 3349 3350 /mnt/cgroup/B/cpuset.cpus cat /mnt/cgroup/B/cpuset.cpus 1 stress -c 2 # 在 A组的 shell 窗口中执行以下命令 stress -c 2 # 在第3个shell窗口中用top命令查看执行结果 top top - 15:20:07 up 1:53, 3 users, load average: 0.38, 0.83, 0.56 Tasks: 78 total, 5 running, 73 sleeping, 0 stopped, 0 zombie %Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 1887872 total, 117340 used, 1770532 free, 11168 buffers KiB Swap: 3982332 total, 0 used, 3982332 free, 47088 cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3854 root 20 0 6524 88 0 R 49.9 0.0 0:03.76 stress 3857 root 20 0 6524 92 0 R 49.9 0.0 0:02.29 stress 3858 root 20 0 6524 92 0 R 49.9 0.0 0:02.29 stress 3855 root 20 0 6524 88 0 R 49.6 0.0 0:03.76 stress 果然, 和预期一致. A组中的 stress 和 B组中的 stress 在各自的物理CPU上都占用了 100% 左右的CPU使用率. 实例4 - cgroup 对使用的内存的控制 cgroup 对内存的控制也很简单, 只要挂载cgroup时, 指定 -o memory # 首先之前挂载的 cpuset 子系统 umount /mnt/cgroup # 挂载cgroup 文件系统, 指定 -o memeory mount -o memory -t cgroup memcg /mnt/cgroup/ mount: special device memcg does not exist 出现以上错误的原因可能是因为debian系统中, 默认没有启动 cgroup 的memory子系统. 可以通过以下方法确认: cat /proc/cgroups #subsys_name hierarchy num_cgroups enabled cpuset 0 1 1 cpu 0 1 1 cpuacct 0 1 1 memory 1 1 0 GRUB_CMDLINE_LINUX="cgroup_enable=memory" # 保存后, 更新grub.cfg update-grub reboot 重启之后, 发现 /proc/cgroups 中的memory已经 enabled, 并且也可以挂载 memcg了 cat /proc/cgroups #subsys_name hierarchy num_cgroups enabled cpuset 0 1 1 cpu 0 1 1 cpuacct 0 1 1 memory 1 1 1 devices 0 1 1 freezer 0 1 1 net_cls 0 1 1 blkio 0 1 1 perf_event 0 1 1 # 挂载cgroup 的memory子系统 mount -t cgroup -o memory memcg /mnt/cgroup ls -l /mnt/cgroup/ /dev/null; free -m; total used free shared buffers cached Mem: 1843 122 1721 0 9 43 -/+ buffers/cache: 68 1774 Swap: 3888 0 3888 total used free shared buffers cached Mem: 1843 1744 99 0 26 1614 -/+ buffers/cache: 104 1739 Swap: 3888 0 3888 # 重启系统 reboot # 挂载 memcg mount -t cgroup -o memory memcg /mnt/cgroup # 创建 组A mkdir /mnt/cgroup/A # 将当前 shell 加入到组A echo ¥¥> /mnt/cgroup/A/tasks # 限制 组A 的内存使用量最大为 10MB echo 10M > /mnt/cgroup/A/memory.limit_in_bytes # 测试限制内存为 10MB 时, 内存的使用情况. rm -rf linux-source-3.2.tar.gz free -m; tar czvf linux-source-3.2.tar.gz /path/to/linux-source-3.2/ > /dev/null; free -m; total used free shared buffers cached Mem: 1843 122 1721 0 10 43 -/+ buffers/cache: 68 1774 Swap: 3888 0 3888 total used free shared buffers cached Mem: 1843 194 1649 0 14 48 -/+ buffers/cache: 131 1712 Swap: 3888 0 3888 从上面的结果可以看出限制内存是起了作用的. 不限制内存时, tar 压缩前后 buffer + cache 内存从 (9MB + 43MB) ==> (26MB + 1614MB) 增大了 1588MB 限制内存后, tar 压缩前后 buffer + cache 内存从 (10MB + 43MB) ==> (14MB + 48MB) 增大了 9MB 总结 简单的实验就发现 cgroup 如此强大的控制能力(而且配置也很简单), 这也就难怪LXC等容器技术能如此强大, 如此流行. cgroup 的配置文件很多, 上面的实例中只简单使用了其中的几个配置文件, 如果想深入了解 cgroup, 更好的利用cgroup的话, 还得找个介绍cgroup配置文件的文档来研究一下, 这篇博客提供的内容还远远不够. |
CopyRight 2018-2019 实验室设备网 版权所有 |